Avastage vÔimsad TypeScripti enum-alternatiivid nagu const assertionid ja union type'id. MÔistke nende eeliseid, puudusi ja praktilist kasutamist puhtama, hooldatavama koodi jaoks globaalses arenduskontekstis.
TypeScript Enum Alternatiivid: Const Assertionite ja Union Type'ide Kasutamine Robustse Koodi Loomiseks
TypeScript, JavaScripti vĂ”imas supersett, toob staatilise tĂŒĂŒbikindluse dĂŒnaamilisse veebiarenduse maailma. Oma paljude funktsioonide hulgas on enum mĂ€rksĂ”na olnud pikka aega nimetatud konstantide kogumi mÀÀratlemiseks. Enum-id pakuvad selget viisi fikseeritud seotud vÀÀrtuste kogumi esitamiseks, parandades loetavust ja tĂŒĂŒbikindlust.
Kuid TypeScripti ökosĂŒsteemi kĂŒpsedes ning projektide keerukuse ja ulatuse kasvades seab globaalselt arendajate seas ĂŒha enam kĂŒsimĂ€rgi alla enum-ite traditsioonilise kasulikkuse. Kuigi lihtsate juhtumite puhul on need arusaadavad, tutvustavad enum-id teatud kĂ€itumisviise ja kĂ€itusaegseid omadusi, mis vĂ”ivad mĂ”nikord pĂ”hjustada ootamatuid probleeme, mĂ”jutada paketi suurust vĂ”i keerustada tree-shaking optimisaatoreid. See on viinud alternatiivide laialdase uurimiseni.
See pĂ”hjalik juhend sĂŒveneb sĂŒgavuti kahesse silmapaistvasse ja vĂ€ga tĂ”husasse alternatiivi TypeScripti enum-itele: Union Type'id koos Stringi/Numbriga Literalsiga ja Const Assertionid (as const). Uurime nende mehhanisme, praktilisi rakendusi, eeliseid ja kompromisse, pakkudes teile teadmisi, et teha teadlikke disainivalikuid oma projektide jaoks, olenemata nende suurusest vĂ”i nende kallal töötavast globaalsest meeskonnast. Meie eesmĂ€rk on anda teile vĂ”imalus kirjutada robustsemat, hooldatavamat ja tĂ”husamat TypeScripti koodi.
TypeScripti Enum: Kiire Kordamine
Enne kui sukeldume alternatiividesse, vaatame lĂŒhidalt traditsioonilist TypeScripti enum. Enum-id vĂ”imaldavad arendajatel mÀÀratleda nimetatud konstantide kogumi, muutes koodi loetavamaks ja vĂ€ltides "maagiliste stringide" vĂ”i "maagiliste numbrite" hajutamist kogu rakenduses. Need esinevad kahes peamises vormis: numbrilised ja string-enumid.
Numbrilised Enum-id
Vaikimisi on TypeScripti enum-id numbrilised. Esimene liige initialiseeritakse vÀÀrtusega 0 ja iga jÀrgnev liige suureneb automaatselt.
enum Direction {
Up,
Down,
Left,
Right,
}
let currentDirection: Direction = Direction.Up;
console.log(currentDirection); // VĂ€ljund: 0
console.log(Direction.Left); // VĂ€ljund: 2
VÔite ka numbrilisi enum-liikmeid kÀsitsi initialiseerida:
enum StatusCode {
Success = 200,
NotFound = 404,
ServerError = 500,
}
let status: StatusCode = StatusCode.NotFound;
console.log(status); // VĂ€ljund: 404
Numbriliste enum-ite eripÀra on pöörd-mapping. KÀituse ajal kompileeritakse numbriline enum JavaScripti objektiks, mis mapib nii nimed vÀÀrtustele kui ka vÀÀrtused nimedele.
enum UserRole {
Admin = 1,
Editor,
Viewer,
}
console.log(UserRole[1]); // VĂ€ljund: "Admin"
console.log(UserRole.Editor); // VĂ€ljund: 2
console.log(UserRole[2]); // VĂ€ljund: "Editor"
/*
Kompileerub JavaScripti:
var UserRole;
(function (UserRole) {
UserRole[UserRole["Admin"] = 1] = "Admin";
UserRole[UserRole["Editor"] = 2] = "Editor";
UserRole[UserRole["Viewer"] = 3] = "Viewer";
})(UserRole || (UserRole = {}));
*/
String-Enum-id
String-enum-id eelistatakse sageli nende loetavuse tÔttu kÀituse ajal, kuna need ei tugine automaatselt kasvavatele numbritele. Iga liige tuleb initialiseerida stringi literaliga.
enum UserPermission {
Read = "READ_PERMISSION",
Write = "WRITE_PERMISSION",
Delete = "DELETE_PERMISSION",
}
let permission: UserPermission = UserPermission.Write;
console.log(permission); // VĂ€ljund: "WRITE_PERMISSION"
String-enum-idel ei ole pöörd-mappingut, mis on ĂŒldiselt hea asi, et vĂ€ltida ootamatut kĂ€itusaegset kĂ€itumist ja vĂ€hendada genereeritud JavaScripti vĂ€ljundit.
Peamised Kaalutlused ja VÔimalikud Ohud Enum-itel
Kuigi enum-id pakuvad mugavust, on neil teatud omadusi, mis nÔuavad hoolikat kaalumist:
- KĂ€itusaja Objektid: Nii numbrilised kui ka string-enum-id loovad kĂ€ituse ajal JavaScripti objekte. See tĂ€hendab, et need aitavad kaasa rakenduse paketi suurusele, isegi kui neid kasutatakse ainult tĂŒĂŒbikontrolliks. VĂ€ikeste projektide puhul vĂ”ib see olla tĂ€htsusetu, kuid suuremahulistes rakendustes, kus on palju enum-eid, vĂ”ib see kokku liita.
- Tree-Shakingu Puudumine: Kuna enum-id on kĂ€itusaja objektid, ei tree-shake neid sageli kaasaegsete bundlerite nagu Webpack vĂ”i Rollup poolt tĂ”husalt. Kui te defineerite enum-i, kuid kasutate ainult ĂŒhte vĂ”i kahte selle liiget, vĂ”ib kogu enum-i objekt siiski lĂ”plikku paketti lisada. See vĂ”ib viia suuremate failisuurusteni kui vajalik.
- Pöörd-Mapping (Numbrilised Enum-id): Numbriliste enum-ite pöörd-mapping funktsioon, kuigi mÔnikord kasulik, vÔib olla ka segaduse ja ootamatu kÀitumise allikas. See lisab JavaScripti vÀljundisse tÀiendavat koodi ja ei pruugi alati olla soovitud funktsionaalsus. NÀiteks numbriliste enum-ite serialiseerimine vÔib mÔnikord viia ainult numbri salvestamiseni, mis ei pruugi olla nii kirjeldav kui string.
- Transpilatsiooni Ălekoormus: Enum-ite kompileerimine JavaScripti objektideks lisab ehitusprotsessile kerge ĂŒlekoormuse vĂ”rreldes lihtsalt konstantide defineerimisega.
- Piiratud Iteratsioon: Enum-vÀÀrtuste otse itereerimine vĂ”ib olla mitte-triviaalselt, eriti numbriliste enum-ite puhul pöörd-mappingu tĂ”ttu. Sageli vajate abifunktsioone vĂ”i spetsiifilisi tsĂŒkleid, et saada ainult soovitud vÀÀrtused.
Need punktid toovad esile, miks paljud globaalsed arendusmeeskonnad, eriti need, kes keskenduvad jĂ”udlusele ja paketi suurusele, otsivad alternatiive, mis pakuvad sarnast tĂŒĂŒbikindlust ilma kĂ€ituse jalajĂ€ljeta vĂ”i muude keerukusteta.
Alternatiiv 1: Union Type'id koos Literalsiga
Ăks kĂ”ige sirgjoonelisemaid ja vĂ”imsamaid alternatiive enum-itele TypeScriptis on Union Type'id koos Stringi vĂ”i Numbriga Literalsiga. See lĂ€henemisviis kasutab TypeScripti robustset tĂŒĂŒbisĂŒsteemi, et mÀÀratleda spetsiifiliste, lubatud vÀÀrtuste kogum compile-time'is, ilma et see tooks kĂ€ituse ajal uusi konstruktsioone.
Mis on Union Type'id?
Union type kirjeldab vÀÀrtust, mis vĂ”ib olla ĂŒks mitmest tĂŒĂŒbist. NĂ€iteks string | number tĂ€hendab, et muutuja vĂ”ib sisaldada kas stringi vĂ”i numbrit. Kui kombineerida literal tĂŒĂŒpidega (nt "success", 404), saate mÀÀratleda tĂŒĂŒbi, mis vĂ”ib sisaldada ainult teatud eelnevalt mÀÀratletud vÀÀrtuste kogumit.
Praktiline NÀide: Oleku MÀÀratlemine Union Type'idega
Kaalume tavalist stsenaariumi: andmetöötlusĂŒlesande vĂ”i kasutajakonto vĂ”imalikud olekud. Union type'idega nĂ€eb see vĂ€lja puhas ja lĂŒhike:
type JobStatus = "PENDING" | "IN_PROGRESS" | "COMPLETED" | "FAILED";
function processJob(status: JobStatus): void {
if (status === "COMPLETED") {
console.log("Töö lÔppes edukalt.");
} else if (status === "FAILED") {
console.log("Tööga tekkis viga.");
} else {
console.log(`Töö on praegu ${status}.`);
}
}
let currentJobStatus: JobStatus = "IN_PROGRESS";
processJob(currentJobStatus);
// See tekitaks compile-time vea:
// let invalidStatus: JobStatus = "CANCELLED"; // Viga: TĂŒĂŒp '"CANCELLED"' ei ole assigneeritav tĂŒĂŒbile 'JobStatus'.
Numbriliste vÀÀrtuste puhul on muster identne:
type HttpCode = 200 | 400 | 404 | 500;
function handleResponse(code: HttpCode): void {
if (code === 200) {
console.log("Toiming edukas.");
} else if (code === 404) {
console.log("Resurssi ei leitud.");
}
}
let responseStatus: HttpCode = 200;
handleResponse(responseStatus);
Pange tÀhele, kuidas me siin type aliast defineerime. See on puhtalt compile-time konstruktsioon. Kui see kompileeritakse JavaScriptiks, JobStatus lihtsalt kaob ja stringid/numbrid ise kasutatakse otse.
Union Type'ide Eelised Literalsiga
See lÀhenemisviis pakub mitmeid veenvaid eeliseid:
- Puhtalt Compile-Time: Union type'id kustutatakse kompileerimise ajal tÀielikult. Need ei genereeri kÀituse ajal mingit JavaScripti koodi, mis toob kaasa vÀiksemad paketi suurused ja kiiremad rakenduse kÀivitusaajad. See on oluline eelis jÔudluskriitiliste rakenduste ja globaalselt juurutatavate rakenduste jaoks, kus iga kilobait loeb.
- SuurepĂ€rane TĂŒĂŒbikindlus: TypeScript kontrollib rangelt assigneeringuid mÀÀratletud literal tĂŒĂŒpide suhtes, pakkudes tugevaid garantiisid, et kasutatakse ainult kehtivaid vÀÀrtusi. See hoiab Ă€ra tĂŒĂŒpilised tĂŒpoode vĂ”i valesid vÀÀrtusi sisaldavad vead.
- Optimaalne Tree-Shaking: Kuna kÀitusaja objekti pole, toetavad union type'id loomulikult tree-shakingut. Teie bundler sisaldab ainult tegelikke stringi vÔi numbrilisi literaleid, mida te kasutate, mitte kogu objekti.
- Loetavus: Lihtsate, erinevate vÀÀrtuste fikseeritud kogumi puhul on tĂŒĂŒbi definitsioon sageli vĂ€ga selge ja kergesti mĂ”istetav.
- Lihtsus: Uusi keelekonstruktsioone ega keerulisi kompilatsiooni artefakte ei tutvustata. See lihtsalt kasutab TypeScripti tĂŒĂŒpide pĂ”hiomadusi.
- Otsene VÀÀrtuse JuurdepÀÀs: Te töötate otse stringi vÔi numbri vÀÀrtustega, mis lihtsustab serialiseerimist ja deserialiseerimist, eriti API-de vÔi andmebaasidega suheldes, mis ootavad spetsiifilisi string identifikaatoreid.
Union Type'ide Puudused Literalsiga
Kuigi vÔimsad, on union type'idel ka mÔned piirangud:
- Kordus Seotud Andmete Jaoks: Kui teil on vaja seostada tÀiendavaid andmeid vÔi metaandmeid iga "enum" liikmega (nt kuvatav silt, ikoon, vÀrv), ei saa te seda teha otse union type definitsioonis. Tavaliselt vajate eraldi mappimisobjekti.
- Ei Otsest Iteratsiooni KÔigile VÀÀrtustele: KÀituse ajal pole sisseehitatud viisi, kuidas kÔigist vÔimalikest vÀÀrtustest union type'ist saada. NÀiteks te ei saa
JobStatus-est kergesti saada["PENDING", "IN_PROGRESS", "COMPLETED", "FAILED"]. See nĂ”uab sageli eraldi massiivi sĂ€ilitamist, kui teil on vaja neid UI-s kuvada (nt rippmenĂŒĂŒ). - VĂ€hem Tsentraliseeritud: Kui vÀÀrtuste kogumit on vaja nii tĂŒĂŒbina kui ka kĂ€itusaja vÀÀrtuste massiivina, vĂ”ite leida end defineerimas loendit kaks korda (kord tĂŒĂŒbina, kord kĂ€itusaja massiivina), mis vĂ”ib pĂ”hjustada potentsiaalseid sĂŒnkroonimisest vĂ€ljumisi.
Nendest puudustest hoolimata pakuvad union type'id paljudes stsenaariumides puhast, jĂ”udlust ja tĂŒĂŒbikindlat lahendust, mis on kooskĂ”las kaasaegsete JavaScripti arenduspraktikatega.
Alternatiiv 2: Const Assertionid (as const)
as const assertion, mis tutvustati TypeScript 3.4-s, on veel ĂŒks uskumatult vĂ”imas tööriist, mis pakub suurepĂ€rast alternatiivi enum-itele, eriti kui vajate kĂ€itusaja objekti ja robustset tĂŒĂŒbi inferentseerimist. See vĂ”imaldab TypeScriptil literal-avaldiste jaoks kĂ”ige kitsama vĂ”imaliku tĂŒĂŒbi infereerida.
Mis on Const Assertionid?
Kui rakendate as const muutuja, massiivi vĂ”i objekti literalile, kĂ€sitleb TypeScript kĂ”iki literal-i sees olevaid omadusi kui readonly ja infereerib nende literal tĂŒĂŒbid laiade tĂŒĂŒpide asemel (nt "foo" asemel string, 123 asemel number). See vĂ”imaldab tuletada kĂ€itusaja andmestruktuuridest vĂ€ga spetsiifilisi union type'e.
Praktiline NĂ€ide: "Pseudo-Enum" Objekti Loomine as const abil
Vaatame uuesti meie töö oleku nĂ€idet. as const abil saame mÀÀratleda ĂŒhe tĂ”eallika oma olekute jaoks, mis toimib nii kĂ€itusaja objekti kui ka tĂŒĂŒbi definitsioonide alusena.
const JobStatuses = {
PENDING: "PENDING",
IN_PROGRESS: "IN_PROGRESS",
COMPLETED: "COMPLETED",
FAILED: "FAILED",
} as const;
// JobStatuses.PENDING on nĂŒĂŒd infereeritud kui tĂŒĂŒp "PENDING" (mitte lihtsalt string)
// JobStatuses on infereeritud kui tĂŒĂŒp {
// readonly PENDING: "PENDING";
// readonly IN_PROGRESS: "IN_PROGRESS";
// readonly COMPLETED: "COMPLETED";
// readonly FAILED: "FAILED";
// }
Sel hetkel on JobStatuses kĂ€itusajal JavaScripti objekt, nagu tavaline enum. Selle tĂŒĂŒbi inferentseerimine on aga palju tĂ€psem.
Kombineerimine typeof ja keyof abil Union Type'ide jaoks
TÔeline vÔim ilmneb siis, kui kombineerime as const TypeScripti typeof ja keyof operaatoritega, et tuletada union type objekti vÀÀrtustest vÔi vÔtmetest.
const JobStatuses = {
PENDING: "PENDING",
IN_PROGRESS: "IN_PROGRESS",
COMPLETED: "COMPLETED",
FAILED: "FAILED",
} as const;
// TĂŒĂŒp, mis esindab vĂ”tmeid (nt "PENDING" | "IN_PROGRESS" | ...)
type JobStatusKeys = keyof typeof JobStatuses;
// TĂŒĂŒp, mis esindab vÀÀrtusi (nt "PENDING" | "IN_PROGRESS" | ...)
type JobStatusValues = typeof JobStatuses[keyof typeof JobStatuses];
function processJobWithConstAssertion(status: JobStatusValues): void {
if (status === JobStatuses.COMPLETED) {
console.log("Töö lÔppes edukalt.");
} else if (status === JobStatuses.FAILED) {
console.log("Tööga tekkis viga.");
} else {
console.log(`Töö on praegu ${status}.`);
}
}
let currentJobStatusFromObject: JobStatusValues = JobStatuses.IN_PROGRESS;
processJobWithConstAssertion(currentJobStatusFromObject);
// See tekitaks compile-time vea:
// let invalidStatusFromObject: JobStatusValues = "CANCELLED"; // Viga!
See muster pakub mĂ”lema maailma parimat: kĂ€itusaja objekt itereerimiseks vĂ”i otse omadustele juurdepÀÀsuks ja compile-time union type ranget tĂŒĂŒbikontrolli jaoks.
Const Assertionite Eelised Tuletatud Union Type'idega
- Ăks TĂ”eallikas: Defineerite oma konstandid ĂŒks kord tavalises JavaScripti objektis ja tuletate sellest nii kĂ€itusaja juurdepÀÀsu kui ka compile-time tĂŒĂŒbid. See vĂ€hendab oluliselt kordumist ja parandab hooldatavust erinevate arendusmeeskondade vahel.
- TĂŒĂŒbikindlus: Sarnaselt puhaste union type'idega saate suurepĂ€rase tĂŒĂŒbikindluse, tagades, et kasutatakse ainult eelnevalt mÀÀratletud vÀÀrtusi.
- Itereeritavus KĂ€itusajal: Kuna
JobStatuseson tavaline JavaScripti objekt, saate seda hĂ”lpsalt itereerida selle vĂ”tmeid vĂ”i vÀÀrtusi kasutades standardseid JavaScripti meetodeid naguObject.keys(),Object.values()vĂ”iObject.entries(). See on hindamatu dĂŒnaamiliste UI-de jaoks (nt rippmenĂŒĂŒde tĂ€itmine) vĂ”i mis tahes stseariumide jaoks, mis vajavad kĂ€itusaja loetelu. - Seotud Andmed: See muster toetab loomulikult tĂ€iendavate andmete sidumist iga "enum" liikmega.
- Parem Tree-Shaking Potentsiaal (VÔrreldes Enum-itega): Kuigi
as constloob kĂ€itusaja objekti, on see tavaline JavaScripti objekt. Kaasaegsed bundlerid on ĂŒldiselt tĂ”husamad mittekasutatud omaduste vĂ”i isegi kogu objekti tree-shakingus, kui need pole viidatud, vĂ”rreldes TypeScripti genereeritud enum-objektidega. Siiski, kui objekt on suur ja ainult vĂ€heseid omadusi kasutatakse, vĂ”ib kogu objekt siiski lisada, kui see on imporditud viisil, mis takistab granulaarset tree-shakingut. - Paindlikkus: VĂ”ite defineerida vÀÀrtusi, mis ei ole ainult stringid vĂ”i numbrid, vaid keerukamad objektid vajadusel, muutes selle vĂ€ga paindlikuks mustriks.
const FileOperations = {
UPLOAD: {
label: "Upload File",
icon: "upload-icon.svg",
permission: "can_upload"
},
DOWNLOAD: {
label: "Download File",
icon: "download-icon.svg",
permission: "can_download"
},
DELETE: {
label: "Delete File",
icon: "delete-icon.svg",
permission: "can_delete"
},
} as const;
type FileOperationType = keyof typeof FileOperations; // "UPLOAD" | "DOWNLOAD" | "DELETE"
type FileOperationDetail = typeof FileOperations[keyof typeof FileOperations]; // { label: string; icon: string; permission: string; }
function performOperation(opType: FileOperationType) {
const details = FileOperations[opType];
console.log(`Performing: ${details.label} (Permission: ${details.permission})`);
}
performOperation("UPLOAD");
Const Assertionite Puudused
- KÀitusaja Objekti Olemasolu: Erinevalt puhastest union type'idest loob see lÀhenemisviis kÀituse ajal siiski JavaScripti objekti. Kuigi see on tavaline objekt ja sageli parem tree-shakinguks kui TypeScripti enum-id, ei kustutata seda tÀielikult.
- Kerge VĂ€ljakutsuvam TĂŒĂŒbi Definitseerimine: Union type'i (
keyof typeof ...vĂ”itypeof ...[keyof typeof ...]) tuletamine nĂ”uab natuke rohkem sĂŒntaksit kui lihtsalt literale'ite loetelu union type'i jaoks. - VÀÀrkasutuse Potentsiaal: Kui seda ei kasutata hoolikalt, vĂ”ib vĂ€ga suur
as constobjekt siiski mÀrkimisvÀÀrselt paketi suurusele kaasa aidata, kui selle sisu ei tree-shake'ita tÔhusalt moodulipiiride vahel.
Stsenaariumide puhul, kus vajate nii robustset compile-time tĂŒĂŒbikontrolli kui ka kĂ€itusaja konstantide kogumit, mida saab itereerida vĂ”i mis pakuvad seotud andmeid, on as const sageli eelistatud valik TypeScripti arendajate hulgas ĂŒle maailma.
Alternatiivide VÔrdlus: Millal Mida Kasutada?
Union type'ide ja const assertionite vahel valimine sÔltub suuresti teie konkreetsetest nÔuetest seoses kÀitusaja olemasolu, itereeritavuse ja vajadusega seostada tÀiendavaid andmeid oma konstantidega. Jaotame otsustusfaktorid.
Lihtsus vs. Robustsus
- Union Type'id: Pakuvad ĂŒlimat lihtsust, kui vajate ainult tĂŒĂŒbiga kindlat eristuvate stringi vĂ”i numbriliste vÀÀrtuste kogumit compile-time'is. Need on kĂ”ige kergem valik.
- Const Assertionid: Pakuvad robustsemat mustrit, kui vajate nii compile-time tĂŒĂŒbikindlust kui ka kĂ€itusaja objekti, mida saab pĂ€ringuid teha, itereerida vĂ”i laiendada tĂ€iendava metaandmetega. Esmane seadistus on veidi vĂ€ljakutsuvam, kuid see tasub end funktsioonide osas.
KĂ€itusaja vs. Compile-time Olemasolu
- Union Type'id: On puhtalt compile-time konstruktsioonid. Need ei genereeri absoluutselt mingit JavaScripti koodi. See on ideaalne rakenduste jaoks, kus paketi suuruse minimeerimine on esmatÀhtis ja vÀÀrtused ise on piisavad, ilma et neid oleks vaja kÀitusajal objektina kasutada.
- Const Assertionid: Loovad kĂ€itusajal JavaScripti objekti. See objekt on teie JavaScripti koodis juurdepÀÀsetav ja kasutatav. Kuigi see lisab paketi suurusele, on see ĂŒldiselt tĂ”husam kui TypeScripti enum-id ja paremad kandidaadid tree-shakinguks.
Itereerimise NÔuded
- Union Type'id: Ei paku otsest viisi, kuidas kĂ€itusajal kĂ”igist vĂ”imalikest vÀÀrtustest itereerida. Kui peate tĂ€itma rippmenĂŒĂŒ vĂ”i kuvama kĂ”ik valikud, peate defineerima eraldi massiivi nende vÀÀrtustest, mis vĂ”ib pĂ”hjustada kordusi.
- Const Assertionid: Selles valdkonnas paistavad silma. Kuna töötate tavalise JavaScripti objektiga, saate hÔlpsalt kasutada
Object.keys(),Object.values()vĂ”iObject.entries(), et saada vĂ”tmete, vÀÀrtuste vĂ”i vĂ”tme-vÀÀrtuse paaride massiiv, vastavalt. See muudab need ideaalseks dĂŒnaamiliste UI-de vĂ”i mis tahes stsenaariumide jaoks, mis nĂ”uavad kĂ€itusaja loetelu.
const PaymentMethods = {
CREDIT_CARD: "Credit Card",
PAYPAL: "PayPal",
BANK_TRANSFER: "Bank Transfer",
} as const;
type PaymentMethodType = keyof typeof PaymentMethods;
// Hankige kÔik vÔtmed (nt sisemise loogika jaoks)
const methodKeys = Object.keys(PaymentMethods) as PaymentMethodType[];
console.log(methodKeys); // ["CREDIT_CARD", "PAYPAL", "BANK_TRANSFER"]
// Hankige kĂ”ik vÀÀrtused (nt rippmenĂŒĂŒs kuvamiseks)
const methodLabels = Object.values(PaymentMethods);
console.log(methodLabels); // ["Credit Card", "PayPal", "Bank Transfer"]
// Hankige vÔtme-vÀÀrtuse paarid (nt mappimiseks)
const methodEntries = Object.entries(PaymentMethods);
console.log(methodEntries); // [["CREDIT_CARD", "Credit Card"], ...]
Tree-Shakingu MÔjud
- Union Type'id: On loomulikult tree-shake'itavad, kuna need on ainult compile-time.
- Const Assertionid: Kuigi nad loovad kÀitusaja objekti, suudavad kaasaegsed bundlerid sageli selle objekti mittekasutatud omadusi tÔhusamalt tree-shake'ida kui TypeScripti genereeritud enum-objektidega. Siiski, kui kogu objekt on imporditud ja sellele viidatakse, lisatakse see tÔenÀoliselt. Hoolikas mooduli disain aitab.
Parimad Praktikad ja HĂŒbriidlĂ€henemisviisid
See ei ole alati "kas ĂŒks vĂ”i teine" olukord. Sageli on parim lahendus hĂŒbriidlĂ€henemisviis, eriti suurtes, rahvusvahelistatud rakendustes:
- Lihtsate, puhtalt sisemiste lippude vĂ”i identifikaatorite jaoks, mida kunagi ei pea itereerima ega millel pole seotud andmeid, on Union Type'id ĂŒldiselt kĂ”ige tĂ”husam ja puhtaim valik.
- Konstantide kogumite jaoks, mida tuleb itereerida, UI-des kuvada vÔi millel on rikkalikult seotud metaandmeid (nagu sildid, ikoonid vÔi Ôigused), on Const Assertionite muster parem.
- Kombineerimine Loetavuse ja Lokaliseerimise jaoks: Paljud meeskonnad kasutavad sisemiste identifikaatorite jaoks
as constja tuletavad seejĂ€rel lokaliseeritud kuvatavad sildid eraldi rahvusvahelistamise (i18n) sĂŒsteemist.
// src/constants/order-status.ts
const OrderStatuses = {
PENDING: "PENDING",
PROCESSING: "PROCESSING",
SHIPPED: "SHIPPED",
DELIVERED: "DELIVERED",
CANCELLED: "CANCELLED",
} as const;
type OrderStatus = typeof OrderStatuses[keyof typeof OrderStatuses];
export { OrderStatuses, type OrderStatus };
// src/i18n/en.json
{
"orderStatus": {
"PENDING": "Pending Confirmation",
"PROCESSING": "Processing Order",
"SHIPPED": "Shipped",
"DELIVERED": "Delivered",
"CANCELLED": "Cancelled"
}
}
// src/components/OrderStatusDisplay.tsx
import { OrderStatuses, type OrderStatus } from "../constants/order-status";
import { useTranslation } from "react-i18next"; // NĂ€ide i18n raamatukogust
interface OrderStatusDisplayProps {
status: OrderStatus;
}
function OrderStatusDisplay({ status }: OrderStatusDisplayProps) {
const { t } = useTranslation();
const displayLabel = t(`orderStatus.${status}`);
return <span>Status: {displayLabel}</span>;
}
// Kasutus:
// <OrderStatusDisplay status={OrderStatuses.DELIVERED} />
See hĂŒbriidlĂ€henemisviis kasutab as const tĂŒĂŒbikindlust ja kĂ€itusaja itereeritavust, samal ajal kui hoiab lokaliseeritud kuvatavad stringid eraldi ja hallatavana, mis on globaalsete rakenduste jaoks kriitilise tĂ€htsusega.
TĂ€psemad Mustrid ja Kaalutlused
Lisaks pÔhikÀibele saab nii union type'e kui ka const assertionid integreerida keerukamatesse mustritesse, et veelgi parandada koodi kvaliteeti ja hooldatavust.
Type Guardide Kasutamine Union Type'idega
Union type'idega töötades, eriti kui union sisaldab erinevaid tĂŒĂŒpe (mitte ainult literale'eid), muutuvad type guardid tĂŒĂŒpide kitsendamiseks hĂ€davajalikuks. Literal union type'idega pakuvad diskrimineeritud unionid tohutut jĂ”udu.
type SuccessEvent = { type: "SUCCESS"; data: any; };
type ErrorEvent = { type: "ERROR"; message: string; code: number; };
type SystemEvent = SuccessEvent | ErrorEvent;
function handleSystemEvent(event: SystemEvent) {
if (event.type === "SUCCESS") {
console.log("Andmed saadud:", event.data);
// event on nĂŒĂŒd kitsendatud SuccessEvent'iks
} else {
console.log("Tekkis viga:", event.message, "Kood:", event.code);
// event on nĂŒĂŒd kitsendatud ErrorEvent'iks
}
}
handleSystemEvent({ type: "SUCCESS", data: { user: "Alice" } });
handleSystemEvent({ type: "ERROR", message: "Network failure", code: 503 });
See muster, mida sageli nimetatakse "diskrimineeritud unioniks", on uskumatult robustne ja tĂŒĂŒbikindlusega, pakkudes compile-time garantiisid andmete struktuuri kohta, mis pĂ”hinevad ĂŒhisel literal omadusel (diskriminaator).
Object.values() koos as const ja Type Assertionitega
Kui kasutate as const mustrit, vÔib Object.values() olla vÀga kasulik. Kuid TypeScripti vaikimisi inferentseerimine Object.values() jaoks vÔib olla laiem kui soovitud (nt string[] asemel spetsiifiline union literale'idest). VÔimalikult ranguse saavutamiseks vÔite vajada type assertionit.
const Statuses = {
ACTIVE: "Active",
INACTIVE: "Inactive",
PENDING: "Pending",
} as const;
type StatusValue = typeof Statuses[keyof typeof Statuses]; // "Active" | "Inactive" | "Pending"
// Object.values(Statuses) on infereeritud kui (string | "Active" | "Inactive" | "Pending")[]
// Saame seda vajadusel kitsendada:
const allStatusValues: StatusValue[] = Object.values(Statuses);
console.log(allStatusValues); // ["Active", "Inactive", "Pending"]
// RippmenĂŒĂŒ jaoks vĂ”ite paarida vÀÀrtused siltidega, kui need erinevad
const statusOptions = Object.entries(Statuses).map(([key, value]) => ({
value: key, // Kasutage tegeliku identifikaatorina vÔtit
label: value // Kasutage kuvatava sildina vÀÀrtust
}));
console.log(statusOptions);
/*
[
{ value: "ACTIVE", label: "Active" },
{ value: "INACTIVE", label: "Inactive" },
{ value: "PENDING", label: "Pending" }
]
*/
See demonstreerib, kuidas saada tugevalt tĂŒĂŒbitud vÀÀrtuste massiiv, mis sobib UI elementide jaoks, sĂ€ilitades samal ajal literal tĂŒĂŒbid.
Rahvusvahelistamine (i18n) ja Lokaliseeritud Sildid
Globaalsete rakenduste jaoks on lokaliseeritud stringide haldamine esmatĂ€htis. Kuigi TypeScripti enum-id ja nende alternatiivid pakuvad sisemisi identifikaatoreid, vajavad kuvatavad sildid sageli i18n jaoks eraldamist. as const muster tĂ€iendab i18n sĂŒsteeme kaunilt.
Te defineerite oma sisemised, muutumatud identifikaatorid as const abil. Need identifikaatorid on kĂ”igi lokalsete jaoks ĂŒhtsed ja toimivad teie tĂ”lketoodete vĂ”tmetena. Tegelikud kuvatavad stringid laaditakse seejĂ€rel i18n raamatukogust (nt react-i18next, vue-i18n, FormatJS) kasutaja valitud keele pĂ”hjal.
// app/features/product/constants.ts
export const ProductCategories = {
ELECTRONICS: "ELECTRONICS",
APPAREL: "APPAREL",
HOME_GOODS: "HOME_GOODS",
BOOKS: "BOOKS",
} as const;
export type ProductCategory = typeof ProductCategories[keyof typeof ProductCategories];
// app/i18n/locales/en.json
{
"productCategories": {
"ELECTRONICS": "Electronics",
"APPAREL": "Apparel & Accessories",
"HOME_GOODS": "Home Goods",
"BOOKS": "Books"
}
}
// app/i18n/locales/es.json
{
"productCategories": {
"ELECTRONICS": "ElectrĂłnica",
"APPAREL": "Ropa y Accesorios",
"HOME_GOODS": "ArtĂculos para el hogar",
"BOOKS": "Libros"
}
}
// app/components/ProductCategorySelector.tsx
import { ProductCategories, type ProductCategory } from "../features/product/constants";
import { useTranslation } from "react-i18next";
function ProductCategorySelector() {
const { t } = useTranslation();
return (
<select>
{Object.values(ProductCategories).map(categoryKey => (
<option key={categoryKey} value={categoryKey}>
{t(`productCategories.${categoryKey}`)}
</option>
))}
</select>
);
}
See vastutusala eraldamine on skaleeritavate, globaalsete rakenduste jaoks kriitiline. TypeScripti tĂŒĂŒbid tagavad, et kasutate alati kehtivaid vĂ”tmeid ja i18n sĂŒsteem hoolitseb kasutaja lokaadi pĂ”hjal esitluskihi eest. See vĂ€ldib keelesĂ”ltuvate stringide otse oma peamise rakenduse loogika sisse manustamist, mis on levinud rahvusvaheliste meeskondade jaoks levinud anti-muster.
KokkuvÔte: Oma TypeScripti Disainivalikute TÀiustamine
Kuna TypeScript jĂ€tkuvalt areneb ja annab arendajatele ĂŒle maailma vĂ”imaluse luua robustsemaid ja skaleeritavamaid rakendusi, muutub selle nĂŒansirikka funktsioonide ja alternatiivide mĂ”istmine ĂŒha olulisemaks. Kuigi TypeScripti enum mĂ€rksĂ”na pakub mugavat viisi nimetatud konstantide defineerimiseks, muudavad selle kĂ€itusaja jalajĂ€lg, tree-shakingu piirangud ja pöörd-mappingu keerukused sageli kaasaegsed alternatiivid jĂ”udlusest teadlike vĂ”i suuremahuliste projektide jaoks atraktiivsemaks.
Union Type'id koos Stringi/Numbriga Literalsiga paistavad silma kĂ”ige kergema ja kĂ”ige compile-time-kesksema lahendusena. Need pakuvad kompromissitu tĂŒĂŒbikindlust ilma kĂ€ituse ajal JavaScripti genereerimata, muutes need ideaalseks stsenaariumide jaoks, kus minimaalne paketi suurus ja maksimaalne tree-shaking on prioriteedid ning kĂ€itusaja loetelu pole probleem.
Teisest kĂŒljest pakuvad Const Assertionid (as const) koos typeof ja keyof vĂ€ga paindlikku ja vĂ”imsat mustrit. Need pakuvad ĂŒhte tĂ”eallikat teie konstantidele, tugevat compile-time tĂŒĂŒbikindlust ja kriitilist vĂ”imet itereerida vÀÀrtusi kĂ€itusajal. See lĂ€henemisviis sobib eriti hĂ€sti olukordadesse, kus peate oma konstantidele siduma tĂ€iendavaid andmeid, tĂ€itma dĂŒnaamilisi UI-sid vĂ”i integreeruma sujuvalt rahvusvahelistamise sĂŒsteemidega.
Kaaludes hoolikalt kompromisse â kĂ€itusaja jalajĂ€lg, itereerimisvajadused ja seotud andmete keerukus â saate teha teadlikke otsuseid, mis viivad puhtama, tĂ”husama ja hooldatavama TypeScripti koodini. Nende alternatiivide kasutuselevĂ”tt ei ole ainult "moodsa" TypeScripti kirjutamine; see on teadlike arhitektuuriliste valikute tegemine, mis parandavad teie rakenduse jĂ”udlust, arendaja kogemust ja pikaajalist jĂ€tkusuutlikkust globaalse publiku jaoks.
TÀiustage oma TypeScripti arendust, valides Ôige tööriista Ôige töö jaoks, liikudes vaikimisi enum-ist kaugemale, kui paremad alternatiivid olemas on.